package mqigdcom.mqigd.core;

import android.annotation.TargetApi;
import android.app.Service;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import mqigdcom.mqigd.db.IMQIDao;
import mqigdcom.mqigd.db.MQIDaoImpl;
import mqigdcom.mqigd.db.RoadCondition;
import mqigdcom.mqigd.netapi.NetApiExecutor;
import mqigdcom.mqigd.utils.LogUtils;
import mqigdcom.mqigd.utils.Utils;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * 同步数据的服务
 */
public class SyncDataService extends Service {
    private static final String TAG = SyncDataService.class.getSimpleName();
    private static final int JOB_ID_OF_NETWORK_STATUS = 100;
    private JobScheduler mJobScheduler;
    private NetworkStatusReceiver mNetworkStatusReceiver;
    private IMQIDao mMQIDao;

    @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.d(TAG, "onCreate()");
        mMQIDao = new MQIDaoImpl(this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.d(TAG, "onStartCommand()");
        if (intent != null) {
            uploadData();
        }
        return START_REDELIVER_INTENT;
    }

    /**
     * 将本地已修改的数据，同步到服务器端
     */
    private void uploadData() {
        LogUtils.d(TAG, "uploadData()");
        if (!Utils.isNetworkAvailable(this)) {
            // 设置网络状态的监听
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                startNetworkStatusJobService();
            } else {
                registerNetworkStatusReceiver();
            }
            return;
        }
        if (mMQIDao != null) {
            // 获取需要上传的全部数据
            List<RoadCondition> list = mMQIDao.getNeedUploadRoadConditions();
            if (list != null) {
                for (int i = 0, len = list.size(); i < len; i++) {
                    RoadCondition roadCondition = list.get(i);
                    mMQIDao.updateRoadConditionUploadStatus(roadCondition.get_id(), 1);
                    NetApiExecutor.saveRoadCondition(roadCondition, new UploadCallback(roadCondition.get_id()));
                }
            }
        }
    }

    /**
     * 上传数据的回调
     */
    private class UploadCallback implements Callback<ResponseBody> {

        private int _id;// 路况的记录_id

        UploadCallback(int _id) {
            this._id = _id;
        }

        @Override
        public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
            String res = NetApiExecutor.dealResponse(response);
            if (!TextUtils.isEmpty(res)) {
                try {
                    JSONObject object = new JSONObject(res);
                    int type = object.getInt("type");
                    if (type == 200) {// 上传成功，删除本地的对应记录
                        if (mMQIDao != null) {
                            mMQIDao.deleteRoadConditionById(_id);
                        }
                        LogUtils.d(TAG, "upload succeed:: _id = " + _id + ", msg = " + object.getString("msg"));
                        return;
                    }
                    LogUtils.d(TAG, "upload failed:: _id = " + _id + ", msg = " + object.getString("msg"));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            if (mMQIDao != null) {
                mMQIDao.updateRoadConditionUploadStatus(_id, 0);// 上传失败，重置status为0未上传
            }
            uploadData();// 继续上传数据
        }

        @Override
        public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
            LogUtils.d(TAG, "upload failed:: _id = " + _id + ", msg = " + t.getLocalizedMessage());
            if (mMQIDao != null) {
                mMQIDao.updateRoadConditionUploadStatus(_id, 0);// 上传失败，重置status为0未上传
            }
            uploadData();// 继续上传数据
        }
    }

    /**
     * 启动网络状态的监听服务
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void startNetworkStatusJobService() {
        cancelJobScheduler();
        mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        final JobInfo.Builder builder = new JobInfo.Builder(JOB_ID_OF_NETWORK_STATUS,
                new ComponentName(this, NetworkStatusJobService.class));
        builder.setMinimumLatency(3000); //执行的最小延迟时间
        builder.setOverrideDeadline(4000);  //执行的最长延时时间
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);// 设置不受限制的网络连接
        builder.setBackoffCriteria(2000, JobInfo.BACKOFF_POLICY_LINEAR);// 设置退避/重试策略
        mJobScheduler.schedule(builder.build());
    }

    /**
     * 取消JobScheduler对网络的监听
     */
    private void cancelJobScheduler() {
        if (mJobScheduler != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mJobScheduler.cancel(JOB_ID_OF_NETWORK_STATUS);
            mJobScheduler = null;
        }
    }

    /**
     * 注册网络状态的广播接收器
     */
    private void registerNetworkStatusReceiver() {
        if (mNetworkStatusReceiver == null) {
            mNetworkStatusReceiver = new NetworkStatusReceiver();
            registerReceiver(mNetworkStatusReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        }
    }

    /**
     * 移除网络状态的广播接收器
     */
    private void unregisterNetworkStatusReceiver() {
        if (mNetworkStatusReceiver != null) {
            unregisterReceiver(mNetworkStatusReceiver);
            mNetworkStatusReceiver = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtils.d(TAG, "onDestroy()");
        cancelJobScheduler();
        unregisterNetworkStatusReceiver();
        mMQIDao.release();
        mMQIDao = null;
    }
}
